package com.example.library.github.promeg.pinyinhelper.interval;


import com.example.library.github.promeg.pinyinhelper.trie.Emit;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class IntervalNode {
    private IntervalNode left = null;
    private IntervalNode right = null;
    private int point;
    private List<Intervalable> intervals = new ArrayList();

    public IntervalNode(List<Emit> intervals) {
        this.point = this.determineMedian(intervals);
        List<Emit> toLeft = new ArrayList();
        List<Emit> toRight = new ArrayList();
        Iterator var4 = intervals.iterator();

        while(var4.hasNext()) {
            Emit interval = (Emit)var4.next();
            if (interval.getEnd() < this.point) {
                toLeft.add(interval);
            } else if (interval.getStart() > this.point) {
                toRight.add(interval);
            } else {
                this.intervals.add(interval);
            }
        }

        if (toLeft.size() > 0) {
            this.left = new IntervalNode(toLeft);
        }

        if (toRight.size() > 0) {
            this.right = new IntervalNode(toRight);
        }

    }

    public int determineMedian(List<Emit> intervals) {
        int start = -1;
        int end = -1;
        Iterator var4 = intervals.iterator();

        while(true) {
            int currentEnd;
            do {
                if (!var4.hasNext()) {
                    return (start + end) / 2;
                }

                Intervalable interval = (Intervalable)var4.next();
                int currentStart = interval.getStart();
                currentEnd = interval.getEnd();
                if (start == -1 || currentStart < start) {
                    start = currentStart;
                }
            } while(end != -1 && currentEnd <= end);

            end = currentEnd;
        }
    }

    public List<Intervalable> findOverlaps(Intervalable interval) {
        List<Intervalable> overlaps = new ArrayList();
        if (this.point < interval.getStart()) {
            this.addToOverlaps(interval, overlaps, this.findOverlappingRanges(this.right, interval));
            this.addToOverlaps(interval, overlaps, this.checkForOverlapsToTheRight(interval));
        } else if (this.point > interval.getEnd()) {
            this.addToOverlaps(interval, overlaps, this.findOverlappingRanges(this.left, interval));
            this.addToOverlaps(interval, overlaps, this.checkForOverlapsToTheLeft(interval));
        } else {
            this.addToOverlaps(interval, overlaps, this.intervals);
            this.addToOverlaps(interval, overlaps, this.findOverlappingRanges(this.left, interval));
            this.addToOverlaps(interval, overlaps, this.findOverlappingRanges(this.right, interval));
        }

        return overlaps;
    }

    protected void addToOverlaps(Intervalable interval, List<Intervalable> overlaps, List<Intervalable> newOverlaps) {
        Iterator var4 = newOverlaps.iterator();

        while(var4.hasNext()) {
            Intervalable currentInterval = (Intervalable)var4.next();
            if (!currentInterval.equals(interval)) {
                overlaps.add(currentInterval);
            }
        }

    }

    protected List<Intervalable> checkForOverlapsToTheLeft(Intervalable interval) {
        return this.checkForOverlaps(interval, Direction.LEFT);
    }

    protected List<Intervalable> checkForOverlapsToTheRight(Intervalable interval) {
        return this.checkForOverlaps(interval, Direction.RIGHT);
    }

    protected List<Intervalable> checkForOverlaps(Intervalable interval,IntervalNode.Direction direction) {
        List<Intervalable> overlaps = new ArrayList();
        Iterator var4 = this.intervals.iterator();

        while(var4.hasNext()) {
            Intervalable currentInterval = (Intervalable)var4.next();
            switch(direction) {
                case LEFT:
                    if (currentInterval.getStart() <= interval.getEnd()) {
                        overlaps.add(currentInterval);
                    }
                    break;
                case RIGHT:
                    if (currentInterval.getEnd() >= interval.getStart()) {
                        overlaps.add(currentInterval);
                    }
            }
        }

        return overlaps;
    }

    protected List<Intervalable> findOverlappingRanges(IntervalNode node, Intervalable interval) {
        return node != null ? node.findOverlaps(interval) : Collections.emptyList();
    }

    private static enum Direction {
        LEFT,
        RIGHT;

        private Direction() {
        }
    }
}
